﻿

#region Using Statements

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Threading;
using System.ComponentModel;
using System.Reflection;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Design;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using Freeform;
using FGame = Freeform.Game;
using XGame = Microsoft.Xna.Framework.Game;

#endregion


namespace Freeform
{
    /// <summary>
    /// The input manager is used to check keyboard and mouse input.
    /// </summary>
    public class InputManager : Component
    {

        #region Events

        /// <summary>
        /// This event is fired whenever a key is pressed.
        /// </summary>
        public event InputEventHandler KeysPressed;
        public delegate void InputEventHandler(List<Keys> Keys);

        #endregion


        #region Members

        /// <summary>
        /// Gets the KeyboardState as of the most recent update.
        /// </summary>
        public KeyboardState KeyState_Current { get; private set; }


        /// <summary>
        /// Gets the KeyboardState of the previous update.
        /// </summary>
        public KeyboardState KeyState_Previous { get; private set; }


        /// <summary>
        /// Gets the MouseState as of the most recent update.
        /// </summary>
        public MouseState MouseState_Current { get; private set; }


        /// <summary>
        /// Gets the MouseState of the previous update.
        /// </summary>
        public MouseState MouseState_Previous { get; private set; }


        /// <summary>
        /// Gets an array of Keys that are pressed as of the most recent update.
        /// </summary>
        public Keys[] PressedKeys_Current { get; private set; }


        /// <summary>
        /// Gets an array of Keys that were pressed last update.
        /// </summary>
        public Keys[] PressedKeys_Previous { get; private set; }


        /// <summary>
        /// Gets or sets whether text input from the user should be captured.
        /// </summary>
        public Boolean CaptureText { get; set; }


        /// <summary>
        /// Gets the text that has been collected while CaptureText has been turned on.
        /// </summary>
        private String Text { get; set; }

        #endregion


        #region Initialisation

        /// <summary>
        /// Creates a new Input Manager
        /// </summary>
        /// <param name="Game">The game that the input manager is working for.</param>
        internal InputManager(IGame Game)
            : base(Game.ComponentList)
        {
            Text = "";
            CaptureText = false;
        }

        #endregion


        #region Update

        /// <summary>
        /// Allows the input manager to update the current input states.
        /// </summary>
        /// <param name="Time">Provides a snapshot of timing values.</param>
        public override void Update(GameTime Time)
        {
            base.Update(Time);

            // Update input states.
            KeyboardState KeyState = Keyboard.GetState();

            KeyState_Previous = KeyState_Current;
            KeyState_Current = KeyState;
            MouseState_Previous = MouseState_Current;
            MouseState_Current = Mouse.GetState();
            PressedKeys_Previous = PressedKeys_Current;
            PressedKeys_Current = KeyState.GetPressedKeys();

            // Check for freshly pressed keys.
            List<Keys> List = new List<Keys>();

            foreach (Keys K in PressedKeys_Current)
                if (!PressedKeys_Previous.Contains(K))
                    List.Add(K);

            if (List.Count > 0 && KeysPressed != null)
                KeysPressed(List);

            if (CaptureText)
            {
                foreach (Keys K in List)
                {
                    switch (K)
                    {
                        case Keys.Space: Text += " "; break;
                        //case Keys.Enter: Text += "\n"; break;
                        case Keys.Back: if (Text.Length > 0) Text = Text.Substring(0, Text.Length - 1); break;
                        case Keys.A: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "A" : "a"; break;
                        case Keys.B: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "B" : "b"; break;
                        case Keys.C: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "C" : "c"; break;
                        case Keys.D: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "D" : "d"; break;
                        case Keys.E: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "E" : "e"; break;
                        case Keys.F: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "F" : "f"; break;
                        case Keys.G: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "G" : "g"; break;
                        case Keys.H: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "H" : "h"; break;
                        case Keys.I: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "I" : "i"; break;
                        case Keys.J: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "J" : "j"; break;
                        case Keys.K: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "K" : "k"; break;
                        case Keys.L: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "L" : "l"; break;
                        case Keys.M: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "M" : "m"; break;
                        case Keys.N: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "N" : "n"; break;
                        case Keys.O: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "O" : "o"; break;
                        case Keys.P: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "P" : "p"; break;
                        case Keys.Q: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "Q" : "q"; break;
                        case Keys.R: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "R" : "r"; break;
                        case Keys.S: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "S" : "s"; break;
                        case Keys.T: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "T" : "t"; break;
                        case Keys.U: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "U" : "u"; break;
                        case Keys.V: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "V" : "v"; break;
                        case Keys.W: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "W" : "w"; break;
                        case Keys.X: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "X" : "x"; break;
                        case Keys.Y: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "Y" : "y"; break;
                        case Keys.Z: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "Z" : "z"; break;
                        case Keys.OemComma: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "<" : ","; break;
                        case Keys.OemPeriod: Text += KeyState.IsKeyDown(Keys.LeftShift) ? ">" : "."; break;
                        case Keys.OemQuestion: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "?" : "/"; break;
                        case Keys.OemBackslash: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "|" : "\\"; break;
                        case Keys.OemQuotes: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "\"" : "'"; break;
                        case Keys.OemSemicolon: Text += KeyState.IsKeyDown(Keys.LeftShift) ? ":" : ";"; break;
                        case Keys.OemMinus: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "_" : "-"; break;
                        case Keys.OemPlus: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "+" : "="; break;
                        case Keys.D0: Text += KeyState.IsKeyDown(Keys.LeftShift) ? ")" : "0"; break;
                        case Keys.D1: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "!" : "1"; break;
                        case Keys.D2: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "@" : "2"; break;
                        case Keys.D3: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "#" : "3"; break;
                        case Keys.D4: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "$" : "4"; break;
                        case Keys.D5: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "%" : "5"; break;
                        case Keys.D6: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "^" : "6"; break;
                        case Keys.D7: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "&" : "7"; break;
                        case Keys.D8: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "*" : "8"; break;
                        case Keys.D9: Text += KeyState.IsKeyDown(Keys.LeftShift) ? "(" : "9"; break;

                        default: break;
                    }
                }
            }
        }

        #endregion


        #region Utility

        /// <summary>
        /// When CaptureText has been enabled for a period of time, the text captured can be retrieved with this method.
        /// </summary>
        /// <returns>The captured text.</returns>
        public String GetCapturedText() { return Text; }


        // Resets the text captured when CaptureText was on.
        public void ResetText() { Text = ""; }

        #endregion

    }
}